# +----------------------------------------------------------------------
# | ChatWork
# +----------------------------------------------------------------------
# | 这不是一个自由软件,您只能在不用于商业目的的前提下对程序代码进行修改和使用。
# | 任何企业和个人不允许对程序代码以任何形式任何目的再发布,商业使用请获取授权。
# +----------------------------------------------------------------------
# | Author: ChatWork Team <2474369941@qq.com>
# +----------------------------------------------------------------------
import time
from typing import List
from exception import AppException
from common.utils.urls import UrlUtil
from common.utils.times import TimeUtil
from common.enums.agent import AgentEnum
from common.models.users import UserModel
from common.models.agents import AgentKnowModel
from common.models.agents import AgentKnowTeamedModel
from apps.api.schemas.agent.know import teamed_schema as schema


class KnowTeamedService:
    """ 知识库团队服务类 """

    POWER_VIEW = AgentEnum.POWER_VIEW    # 查看者
    POWER_EDIT = AgentEnum.POWER_EDIT    # 编辑者
    POWER_ADMIN = AgentEnum.POWER_ADMIN  # 管理者
    POWER_OWNED = AgentEnum.POWER_OWNED  # 拥有者

    @classmethod
    async def find_user(cls, params: schema.KnowTeamedSearchIn) -> schema.KnowTeamedUserVo:
        """
        知识库成员查找。

        Args:
            params (schema.KnowTeamedSearchIn): 成员搜索参数。

        Returns:
            List[schema.KnowTeamedUserVo]: 当前用户的权限。

        Author:
            zero
        """
        if not params.keyword:
            raise AppException("请输入需查找的用户编号!")

        user = await UserModel.filter(sn=params.keyword).first()
        if user is None:
            raise AppException("搜索不到该用户，请输入正确的用户编号!")

        know = await AgentKnowModel.filter(code=params.ap_code, is_delete=0).first()
        if know is None:
            raise AppException("知识库已不存在，请刷新页面再重试吧!")

        if know.user_id == user.id:
            raise AppException("该用户是本团队管理员，请务重复绑定!")

        member = await AgentKnowTeamedModel.filter(know_id=know.id, user_id=user.id).first()
        if member:
            raise AppException("该用户是本团队的成员，无需重复绑定!")

        return schema.KnowTeamedUserVo(
            sn=user.sn,
            nickname=user.nickname,
            avatar=await UrlUtil.to_absolute_url(user.avatar)
        )

    @classmethod
    async def lists(cls, user_id: int, params: schema.KnowTeamedSearchIn) -> List[schema.KnowTeamedListVo]:
        """
        知识库成员列表。

        Args:
            user_id (int): 用户ID
            params (schema.KnowTeamedSearchIn): 成员搜索参数。

        Returns:
            List[schema.KnowTeamedListVo]: 当前用户的权限。

        Author:
            zero
        """
        # 验证知识库
        know = await AgentKnowModel.filter(code=params.ap_code, is_delete=0).first()
        if know is None:
            raise AppException("知识库不存在!")

        # 验证权限
        if know.user_id != user_id:
            await cls.has_permission(know.code, user_id, cls.POWER_VIEW)

        # 查询团队
        lists = await AgentKnowTeamedModel.filter(know_id=know.id).all()

        # 提取用户ID
        user_ids = [item.user_id for item in lists if item.user_id]
        users = await UserModel.queryUserDictsById(user_ids)

        _lists = []

        # 知识库拥有者
        owned = await UserModel.filter(id=int(know.user_id)).first()
        _lists.append(schema.KnowTeamedListVo(
            id=0,
            user_sn=owned.sn,
            user_avatar=await UrlUtil.to_absolute_url(owned.avatar),
            user_nickname=owned.nickname,
            power=cls.POWER_OWNED,
            create_time=TimeUtil.timestamp_to_date(owned.create_time),
            update_time=TimeUtil.timestamp_to_date(owned.update_time)
        ))

        # 知识库协作者
        for item in lists:
            user = users.get(item.user_id, {})
            _lists.append(schema.KnowTeamedListVo(
                id=item.id,
                power=item.power,
                user_sn=user.get("sn", ""),
                user_avatar=await UrlUtil.to_absolute_url(user.get("avatar", "")),
                user_nickname=user.get("nickname", ""),
                create_time=TimeUtil.timestamp_to_date(item.create_time),
                update_time=TimeUtil.timestamp_to_date(item.update_time)
            ))

        return _lists

    @classmethod
    async def add(cls, user_id: int, post: schema.KnowTeamedAddIn) -> None:
        """
        知识库成员添加。

        Args:
            user_id (str): 操作用户ID。
            post (schema.KnowTeamedAddIn): 添加参数。

        Author:
            zero
        """
        # 验知识库
        know = await AgentKnowModel.filter(code=post.ap_code, is_delete=0).first()
        if know is None:
            raise AppException("知识库不存在!")
        if know.is_disable:
            raise AppException("知识库已禁用!")

        # 验证用户
        user = await UserModel.filter(sn=post.user_sn).first()
        if user is None:
            raise AppException("用户不存在!")
        if user.is_disable == 1:
            raise AppException("用户被限制!")

        # 验证成员
        member = await AgentKnowTeamedModel.filter(know_id=know.id, user_id=user.id).first()
        if member or know.user_id == user.id:
            raise AppException("用户已存在团队中了!")

        # 如果不是拥有者 并且 需要添加管理员
        if know.user_id != user_id and post.power == cls.POWER_ADMIN:
            # 验证添加的权限
            if post.power == cls.POWER_ADMIN:
                raise AppException("抱歉了,添加管理员需知识库拥有者操作!")
            # 验证操作的权限
            my = await AgentKnowTeamedModel.filter(know_id=know.id, user_id=user_id).first()
            if my is None or my.power != cls.POWER_ADMIN:
                raise AppException("抱歉了,您不具备添加成员的操作权限!")

        # 添加到团队中
        await AgentKnowTeamedModel.create(
            know_id=know.id,
            user_id=user.id,
            power=post.power,
            create_time=int(time.time()),
            update_time=int(time.time())
        )

    @classmethod
    async def edit(cls, user_id: int, post: schema.KnowTeamedEditIn) -> None:
        """
        知识库成员编辑。

        Args:
            user_id (str): 操作用户ID。
            post (schema.KnowTeamedEditIn): 编辑参数。

        Author:
            zero
        """
        # 验证成员
        teamed = await AgentKnowTeamedModel.filter(id=post.id).first()
        if teamed is None:
            raise AppException("成员记录不存在!")

        # 验知识库
        know = await AgentKnowModel.filter(id=teamed.know_id, is_delete=0).first()
        if know is None:
            raise AppException("知识库不存在!")
        if know.is_disable:
            raise AppException("知识库已禁用!")

        # 如果不是知识库拥有者
        if know.user_id != user_id:
            # 验证是否是管理员
            my = await AgentKnowTeamedModel.filter(know_id=know.id, user_id=user_id).first()
            if my.power != cls.POWER_ADMIN:
                raise AppException("抱歉了,该操作仅管理员可用!")
            # 如果数据是管理员
            if teamed.power == cls.POWER_ADMIN:
                raise AppException("抱歉了,您无权限修改管理员!")

        # 自己不能修改自己
        if teamed.user_id == user_id:
            raise AppException("抱歉了,您不能修改自己权限!")

        # 更新权限信息
        await AgentKnowTeamedModel.filter(id=post.id).update(
            power=post.power,
            update_time=int(time.time())
        )

    @classmethod
    async def exits(cls, user_id: int, kb: str) -> None:
        """
        知识库成员退出。

        Args:
            user_id (str): 操作用户ID。
            kb (str): 知识库编号。

        Author:
            zero
        """
        # 验知识库
        know = await AgentKnowModel.filter(code=kb, is_delete=0).first()
        if know is None:
            raise AppException("知识库不存在!")
        if know.is_disable:
            raise AppException("知识库已禁用!")

        # 验证成员
        teamed = await AgentKnowTeamedModel.filter(user_id=user_id, know_id=know.id).first()
        if teamed is None:
            raise AppException("您不是团队成员!")

        # 移除成员
        await AgentKnowTeamedModel.filter(id=teamed.id).delete()

    @classmethod
    async def delete(cls, user_id: int, id_: int) -> None:
        """
        知识库成员删除。

        Args:
            user_id (str): 操作用户ID。
            id_ (int): 成员ID。

        Author:
            zero
        """
        # 验证成员
        teamed = await AgentKnowTeamedModel.filter(id=id_).first()
        if teamed is None:
            raise AppException("成员记录不存在!")

        # 验知识库
        know = await AgentKnowModel.filter(id=teamed.know_id, is_delete=0).first()
        if know is None:
            raise AppException("知识库不存在!")
        if know.is_disable:
            raise AppException("知识库已禁用!")

        # 如果不是知识库拥有者
        if know.user_id != user_id:
            # 验证是否是管理员
            my = await AgentKnowTeamedModel.filter(know_id=know.id, user_id=user_id).first()
            if my.power != cls.POWER_ADMIN:
                raise AppException("抱歉,该操作仅管理员可用!")
            # 如果数据是管理员
            if teamed.power == cls.POWER_ADMIN:
                raise AppException("抱歉,您无权限删除管理员!")

        # 自己不能修改自己
        if teamed.user_id == user_id:
            raise AppException("抱歉,您不能自己删除自己哦!")

        # 删除成员
        await AgentKnowTeamedModel.filter(id=id_).delete()

    @classmethod
    async def has_permission(cls, kb: str, user_id: int, power: int = None) -> int:
        """
        验证用户权限。

        Args:
            kb (str): 知识库编号。
            user_id (str): 用户ID。
            power (str): 最低权限: [1=查看权, 2=编辑权, 3=管理权, 4=所有权]。

        Returns:
            power (int): 当前用户的权限。

        Author:
            zero
        """
        if power is None:
            power = cls.POWER_ADMIN

        know = await AgentKnowModel.filter(code=kb).first().values("id", "code", "user_id", "create_time")
        if int(know["user_id"]) == int(user_id):
            return cls.POWER_OWNED

        member = await AgentKnowTeamedModel.filter(know_id=know["id"], user_id=user_id).first()
        if member is None:
            raise AppException("非法操作,您不是该知识库团队成员!")

        if member.power < power:
            enums = {1: "查看权", 2: "编辑权", 3: "管理权", 4: "拥有权"}
            raise AppException("您无权限操作, 所需权限 ["+enums[power]+"]")

        return member.power
